/* 
 * Copyright 2009 Shared Object (www.sharedobject.ch)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package edos.prm.process;


import java.util.HashSet;
import java.util.Set;

import edos.prm.activity.Activity;
import edos.prm.artifact.Artifact;
import edos.prm.artifact.ArtifactManager;
import edos.prm.artifact.ArtifactSet;
import edos.prm.artifact.AttributePair;
import edos.prm.artifact.Directory;
import edos.prm.artifact.ArtifactManager.PrmArtifactManager;
import edos.prm.engine.PRM;
import edos.prm.project.Project;
import edos.prm.role.RoleException;
import edos.prm.util.Time;
import edos.prm.util.VersionNumber;

/**
 * Process Management interface enabling Process addition, retrieval,
 * execution, etc.
 * 
 * @author Michel Pawlak, Ciaran Bryce
 */
public interface ProcessManager extends Activity {

	/**
	 * Adds a Process to be handled by the ProcessManager for a Project
	 *
	 * @param action teh actions of the process being linked
	 * @param description the description of what the process does
	 * @param name the String name of the process
	 * @param project the project in which the process is being defined
	 * @return a process definition that can be executed within a task
	 * throws RoleException if the caller does not have sufficient privilege
	 */
	public Process newProcess(ProcessAction action, String description,
			String name, Project project) throws RoleException;

	/**
	 * Retrieves all Processes handled by the ProcessManager 
	 *
	 * @return all handled Processes
	 */
	public Set<Process> getProcesses();

	/**
	 * Retrieves all Processes handled by the ProcessManager for a Project
	 *  
	 * @param project Project for which Processes are searched
	 * @return all handled Project's Processes
	 */
	public Set<Process> getProcesses(Project project);

	/**
	 * Searches for Processes matching specified ArtifactDirectory
	 * 
	 * @param attributes Caracteristics to be matched by the Process
	 * @return all processes used by a Project
	 */
	public Set<Process> find(AttributePair<?>...attributes);

	final static class PrmProcessManager implements ProcessManager {
		private HashSet<Process> processes;
		private static PrmProcessManager instance;
		private ArtifactManager am;
		private Time creationDate;

		static {
			instance = new PrmProcessManager();
		}

		public static PrmProcessManager getInstance() {
			return instance;
		}

		private PrmProcessManager() {
			am = PrmArtifactManager.getInstance();
			this.processes = new HashSet<Process>();
			this.creationDate = new Time();
		}

		public Set<Process> find(AttributePair<?>...attributes) {
			HashSet<Process> results = new HashSet<Process>();
			try {
				Directory d = am.lookup(attributes);
				Set<String> properties = d.getContextList();
				if ( properties.size() == 0 )
					return results;
				for ( String property : properties ) {
					ArtifactSet<? extends Artifact> arts = d.select(property);
					for ( Artifact artifact : arts.getContents() )
						if ( artifact instanceof Process )
							results.add((Process)artifact);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			return results;
		}

		public Set<Process> getProcesses() {
			HashSet<Process> result = new HashSet<Process>();
			result.addAll(processes);
			return result;
		}

		public Set<Process> getProcesses(Project project) {
			return getProcesses();
		}

		public Time getCreationDate() {
			return creationDate;
		}

		public String getDescription() {
			return "Default Java Implementation of Process Manager";
		}

		public VersionNumber getVersion() {
			return PRM.getPRMVersion();
		}

		public Process newProcess(ProcessAction action, String text, String string) {
			return new Process.PrmProcess(action, text, string);
		}

		public Process newProcess(ProcessAction action, String description,
				String name, Project project) throws RoleException {
			Process p = new Process.PrmProcess(action, description, name);
			return p;
		}
	}
}
